package com.hitqz.robot.biz.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.cache.Cache;
import com.hitqz.robot.api.business.dto.RobotAddDispatchDto;
import com.hitqz.robot.api.business.dto.RobotClientSummaryDto;
import com.hitqz.robot.api.business.dto.RobotEquipmentPanelDto;
import com.hitqz.robot.api.business.dto.RobotStatusDto;
import com.hitqz.robot.api.business.entity.JobModeEntity;
import com.hitqz.robot.api.business.entity.RobotEntity;
import com.hitqz.robot.api.business.entity.RobotGroupEntity;
import com.hitqz.robot.api.business.entity.RobotMapEntity;
import com.hitqz.robot.api.business.enums.WorkStatusEnum;
import com.hitqz.robot.api.business.params.LogicRobotStatusParams;
import com.hitqz.robot.api.business.vo.LogRobotListVo;
import com.hitqz.robot.api.business.vo.RobotLiveAddressVo;
import com.hitqz.robot.api.business.vo.RobotVo;
import com.hitqz.robot.api.dispatch.protocol.dto.RobotLogicOnlineDto;
import com.hitqz.robot.biz.service.JobModeService;
import com.hitqz.robot.biz.service.RobotGroupService;
import com.hitqz.robot.biz.service.RobotMapService;
import com.hitqz.robot.biz.service.RobotService;
import com.hitqz.robot.common.core.util.R;
import com.hitqz.robot.common.log.annotation.SysLog;
import com.pig4cloud.plugin.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.apache.commons.compress.utils.Lists;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 机器人管理表
 *
 * @author robot
 * @date 2024-06-06 15:18:09
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/robot")
@Tag(description = "robot", name = "机器人管理表管理")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class RobotController {

    private final RobotService robotService;

    private final RobotGroupService robotGroupService;

    private final RobotMapService robotMapService;

    private final JobModeService jobModeService;


    @Operation(summary = "查询在线机器人数据", description = "查询在线机器人数据")
    @GetMapping(value = "onlineRobot")
    public R<List<RobotEntity>> getOnlineRobot() {
        Cache<String, RobotClientSummaryDto> posInfoDtoCache = SpringUtil.getBean("robotCache");
        List<RobotEntity> robotEntityList = Lists.newArrayList();
        for (String robotSn : CollUtil.emptyIfNull(posInfoDtoCache.asMap().keySet())) {
            robotEntityList.add(robotService.selectByRobotSn(robotSn));
        }
        return R.ok(robotEntityList);
    }


    @Operation(summary = "查询所有机器人数据", description = "查询所有机器人数据")
    @GetMapping(value = "list")
    public R<List<RobotEntity>> list() {
        List<RobotEntity> robotEntityList = robotService.list();
        return R.ok(robotEntityList);
    }


    /**
     * 分页查询
     *
     * @param page  分页对象
     * @param robot 机器人管理表
     * @return
     */
    @Operation(summary = "分页查询", description = "分页查询")
    @GetMapping("/page")
    public R<Page<RobotVo>> getRobotPage(@ParameterObject Page page, @ParameterObject RobotEntity robot) {
        LambdaQueryWrapper<RobotEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(robot.getGroupId() != null, RobotEntity::getGroupId, robot.getGroupId() == null ? null : Math.abs(robot.getGroupId()));
        wrapper.eq(StrUtil.isNotBlank(robot.getMapCode()), RobotEntity::getMapCode, robot.getMapCode());
        wrapper.eq(robot.getId() != null, RobotEntity::getId, robot.getId());
        wrapper.like(StrUtil.isNotBlank(robot.getRobotName()), RobotEntity::getRobotName, robot.getRobotName());
        wrapper.eq(StrUtil.isNotBlank(robot.getRobotSn()), RobotEntity::getRobotSn, robot.getRobotSn());
        Page<RobotEntity> pageData = robotService.page(page, wrapper);
        Map<Integer, String> groupMap = robotGroupService.list().stream().collect(Collectors.toMap(RobotGroupEntity::getId, RobotGroupEntity::getName));
        Page<RobotVo> voPage = new Page<>(page.getCurrent(), page.getSize());
        voPage.setTotal(pageData.getTotal());
        List<RobotVo> robotVos = Lists.newArrayList();
        Cache<String, RobotClientSummaryDto> posInfoDtoCache = SpringUtil.getBean("robotCache");
        for (RobotEntity record : CollUtil.emptyIfNull(pageData.getRecords())) {
            RobotVo robotVo = new RobotVo();
            BeanUtil.copyProperties(record, robotVo);
            robotVo.setGroupName(groupMap.get(record.getGroupId()));
            RobotMapEntity robotMap = robotMapService.findByMapCode(record.getMapCode());
            robotVo.setMapName(robotMap != null ? robotMap.getMapName() : robot.getMapCode());
            String onlineStatusStr = Optional.ofNullable(posInfoDtoCache.getIfPresent(record.getRobotSn())).map(RobotClientSummaryDto::getStatus).map(RobotStatusDto::getOnlineStatusStr).orElse("离线");
            robotVo.setOnlineStatusStr(onlineStatusStr);
            robotVos.add(robotVo);
        }
        voPage.setRecords(robotVos);
        return R.ok(voPage);
    }

    /**
     * 返回树形机器人集合
     *
     * @return 树形菜单
     */
    @Operation(summary = "获取树状结构", description = "获取树状结构")
    @GetMapping(value = "/tree")
    public R getTree() {
        return R.ok(robotService.selectTree());
    }


    /**
     * 通过id查询机器人管理表
     *
     * @param id id
     * @return R
     */
    @Operation(summary = "通过id查询", description = "通过id查询")
    @GetMapping("/{id}")
    public R<RobotEntity> getById(@PathVariable("id") Integer id) {
        RobotEntity robot = robotService.getById(id);
        if (robot != null && robot.getGroupId() > 0) {
            RobotGroupEntity group = robotGroupService.getById(robot.getGroupId());
            robot.setGroupName(group.getName());
        } else {
            robot.setGroupId(1);
        }
        return R.ok(robot);
    }

    /**
     * 新增机器人管理表
     *
     * @param robot 机器人管理表
     * @return R
     */
    @Operation(summary = "新增机器人管理表", description = "新增机器人管理表")
    @SysLog("新增机器人管理表")
    @PostMapping
    @CacheEvict(cacheNames = "robot::client", key = "#robot.robotSn")
    public R save(@RequestBody RobotEntity robot) {
        if (robot.getGroupId() != null) {
            robot.setGroupId(Math.abs(robot.getGroupId()));
        }
        return R.ok(robotService.save(robot));
    }

    /**
     * 修改机器人管理表
     *
     * @param robot 机器人管理表
     * @return R
     */
    @Operation(summary = "修改机器人管理表", description = "修改机器人管理表")
    @SysLog("修改机器人管理表")
    @PutMapping
    @CacheEvict(cacheNames = "robot::client", key = "#robot.robotSn")
    public R updateById(@RequestBody RobotEntity robot) {
        if (robot.getGroupId() != null) {
            robot.setGroupId(Math.abs(robot.getGroupId()));
        }
        RobotEntity robotEntity = robotService.selectByRobotSn(robot.getRobotSn());
        Integer oldGroupId = robotEntity.getGroupId();
        Cache<String, RobotClientSummaryDto> posInfoDtoCache = SpringUtil.getBean("robotCache");
        RobotClientSummaryDto robotClientSummaryDto = posInfoDtoCache.getIfPresent(robotEntity.getRobotSn());
        if (robotClientSummaryDto == null) {
            return R.failed("机器人不在线无法操作");
        }
        SpringUtil.getApplicationContext().publishEvent(robot);
        RobotAddDispatchDto robotAddDispatchDto = new RobotAddDispatchDto();
        robotAddDispatchDto.setRobotSn(robot.getRobotSn());
        robotAddDispatchDto.setOldGroupId(oldGroupId);
        SpringUtil.getApplicationContext().publishEvent(robotAddDispatchDto);
        return R.ok(robotService.updateById(robot));
    }

    /**
     * 通过id删除机器人管理表
     *
     * @param ids id列表
     * @return R
     */
    @Operation(summary = "通过id删除机器人管理表", description = "通过id删除机器人管理表")
    @SysLog("通过id删除机器人管理表")
    @DeleteMapping
    @CacheEvict(cacheNames = "robot::client", key = "#robot.robotSn")
    public R removeById(@RequestBody Integer[] ids) {
        return R.ok(robotService.removeBatchByIds(CollUtil.toList(ids)));
    }


    /**
     * 导出excel 表格
     *
     * @param robot 查询条件
     * @param ids   导出指定ID
     * @return excel 文件流
     */
    @ResponseExcel
    @GetMapping("/export")
    public List<RobotEntity> export(RobotEntity robot, Integer[] ids) {
        return robotService.list(Wrappers.lambdaQuery(robot).in(ArrayUtil.isNotEmpty(ids), RobotEntity::getId, ids));
    }


    @Operation(summary = "获取机器人相机相关外设播放地址")
    @SysLog("获取机器人相机相关外设播放地址")
    @GetMapping(value = "getLiveAddress")
    public R<List<RobotLiveAddressVo>> getLiveAddress(@RequestParam(value = "robotSn") String robotSn) {
        RobotEntity robotEntity = robotService.selectByRobotSn(robotSn);
        Integer oldGroupId = robotEntity.getGroupId();
        Cache<String, RobotClientSummaryDto> posInfoDtoCache = SpringUtil.getBean("robotCache");
        RobotClientSummaryDto robotClientSummaryDto = posInfoDtoCache.getIfPresent(robotEntity.getRobotSn());
        if (robotClientSummaryDto == null) {
            return R.failed("机器人不在线无法操作");
        }
        List<RobotLiveAddressVo> robotLiveAddressVos = Lists.newArrayList();
        RobotEquipmentPanelDto panelDtos = robotClientSummaryDto.getEquipmentPanel();

        if (CollUtil.isEmpty(panelDtos.getPlayUrls())) {
            return R.failed("暂无可查看视频");
        }
        for (String liveAddress : panelDtos.getPlayUrls()) {
            RobotLiveAddressVo robotLiveAddressVo = new RobotLiveAddressVo();
            robotLiveAddressVo.setLiveAddress(liveAddress);
            robotLiveAddressVos.add(robotLiveAddressVo);
        }
        return R.ok(robotLiveAddressVos);
    }


    @Operation(summary = "可获取的日志列表")
    @SysLog("可获取的日志列表")
    @GetMapping(value = "getLogRobotList")
    public R<List<LogRobotListVo>> getLogRobotList() {
        List<LogRobotListVo> logRobotListVos = Lists.newArrayList();
        LogRobotListVo logRobotListVo = new LogRobotListVo();
        logRobotListVo.setLabel("系统日志");
        logRobotListVo.setValue("server");
        logRobotListVos.add(logRobotListVo);
        Cache<String, RobotClientSummaryDto> posInfoDtoCache = SpringUtil.getBean("robotCache");
        for (RobotClientSummaryDto robotClientSummaryDto : posInfoDtoCache.asMap().values()) {
            LogRobotListVo listVo = new LogRobotListVo();
            listVo.setValue(robotClientSummaryDto.getClientId());
            listVo.setLabel(robotService.selectByRobotSn(robotClientSummaryDto.getClientId()).getRobotName());
            logRobotListVos.add(listVo);
        }
        return R.ok(logRobotListVos);
    }


    @PostMapping(value = "changeLogicStatus")
    @Operation(summary = "机器人调度逻辑上线/下线")
    @SysLog("更改机器人逻辑上线下线")
    public R logicStatus(@RequestBody LogicRobotStatusParams logicStatusDto) {
        RobotEntity robotEntity = robotService.selectByRobotSn(logicStatusDto.getClientId());
        Cache<String, RobotClientSummaryDto> posInfoDtoCache = SpringUtil.getBean("robotCache");
        RobotClientSummaryDto robotClientSummaryDto = posInfoDtoCache.getIfPresent(logicStatusDto.getClientId());
        if (robotClientSummaryDto == null || robotClientSummaryDto.getStatus().getOnlineStatus() == 0) {
            return R.failed("机器人不在线,无法操作");
        }
        if(robotClientSummaryDto!=null&&robotClientSummaryDto.getStatus().getWorkStatus()==Integer.parseInt(WorkStatusEnum.WORK.getCode())){
            return R.failed("机器人当前作业中，无法直接下线，请等任务结束后再操作，或者直接清除任务！");
        }
        RobotLogicOnlineDto robotLogicOnlineDto = new RobotLogicOnlineDto();
        robotLogicOnlineDto.setClientId(robotClientSummaryDto.getClientId());
        robotLogicOnlineDto.setLogicOnlineStatus(logicStatusDto.getStatus());
        SpringUtil.getApplicationContext().publishEvent(robotLogicOnlineDto);
        return R.ok();
    }

    /**
     * 查询任务模式
     *
     * @return R
     */
    @Operation(summary = "查询任务模式", description = "查询任务模式")
    @GetMapping("/getJobMode")
    public R<JobModeEntity> getJobMode() {
        return R.ok(jobModeService.getDefaultJobMode());
    }

    /**
     * 修改任务模式
     *
     * @param jobMode 任务模式
     * @return R
     */
    @Operation(summary = "修改任务模式", description = "修改任务模式")
    @SysLog("修改任务模式")
    @PutMapping("/updateJobMode")
    public R<Boolean> updateJobMode(@RequestBody JobModeEntity jobMode) {
        try{
//           return R.failed("暂时不支持切换模式！");
            return R.ok(jobModeService.updateJobMode(jobMode));
        }catch (Exception e){
            return R.failed(e.getMessage());
        }
    }

}